package com.cn.common;

import com.sun.xml.internal.bind.v2.schemagen.xmlschema.NoFixedFacet;

import java.util.HashMap;

public class WaitNotifyObject {

    private final HashMap<Long /*thread Id*/ , Boolean /*notify*/> threadTables = new HashMap<>(16);

    private volatile boolean hasNofity = false;

    protected void onWaitEnd() {
    }

    //唤醒
    public void wakeup() {
        synchronized (this) {
            if (!hasNofity) {
                this.notify();
                this.hasNofity = true;
            }
        }
    }

    public void waitRunning(long internal) {
        synchronized (this) {
            if (hasNofity) {
                this.hasNofity = false;
                this.onWaitEnd();
                return;
            }
            try {
                this.wait(internal);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                this.hasNofity = false;
                this.onWaitEnd();
            }
        }
    }

    public void wakeupAll() {
        synchronized (this) {
            boolean notify = false;
            for (Boolean n : this.threadTables.values()) {
                notify = notify || !n;
                n = true;
            }
            if (notify) {
                this.notifyAll();
            }
        }
    }

    public void allWaitForRunning(long internal) {
        Long id = Thread.currentThread().getId();
        synchronized (this) {
            Boolean notify = this.threadTables.get(id);
            if (notify != null && notify) {
                //该线程是唤醒状态
                this.threadTables.put(id, false);
                this.onWaitEnd();
                return;
            }
            try {
                this.wait(internal);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                this.threadTables.put(id, false);
                this.onWaitEnd();
            }
        }
    }

    public void remove() {
        //当前线程id
        Long id = Thread.currentThread().getId();
        synchronized (this) {
            this.threadTables.remove(id);
        }
    }

}
